package ifierce.traffic.simulator.view;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

import ifierce.traffic.simulator.view.components.SimulationPanel;
import ifierce.traffic.simulator.view.components.ToolBarButton;
import ifierce.traffic.simulator.view.components.ToolBarPanel;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.KeyStroke;

/**
 * Клас представляє базову реалізацію головного вікна програми.
 * @author Igor Fierce
 *
 */
public class View {
	// Оголошуємо поле для збереження фрейму головного вікна програми
	private JFrame frame;
	
	// Оголошуємо поле для збереження панелі меню
	private JMenuBar menuBar;
	
	// Оголошуємо поля для збереження елементів панелі меню
	private JMenu fileMenu, addMenu, runMenu, settingsMenu, helpMenu;
	
	// Оголошуємо поле для збереження панелі інструментів
	private ToolBarPanel toolBarPanel;
	
	// Оголошуємо поле для збереження панелі відображення процесу моделювання
	private SimulationPanel simPanel;
	
	/**
	 * Метод використовується для створення графічних компонентів головного вікна.
	 */
	public void createGui() {
		// Створюємо фрейм та здійснюємо його налаштовування
		createFrame();
		
		// Створюємо панель меню та здійснюємо налаштовування його елементів
		createMenuBar();
		
		// Створюємо панель інструментів та здійснюємо налаштовування її елементів
		createToolBar();
		
		// Додаємо компоненти головного вікна програми до фрейму
		frame.setJMenuBar(menuBar);
		frame.getContentPane().add(toolBarPanel);
		
		// Відображаємо фрейм
		frame.setVisible(true);
	}

	/**
	 * Метод створює фрейм головного вікна програми та здійснює його налаштовування.
	 */
	private void createFrame() {
		// Створюємо фрейм головного вікна програми
		frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		// Встановлюємо розміри фрейму
		Toolkit toolkit = Toolkit.getDefaultToolkit();
		Dimension screenSize = toolkit.getScreenSize();
		screenSize.height /= 2;
		screenSize.width /= 2;
		frame.setSize(screenSize);
		setPositionToCenter(frame);
		
		// Встановлюємо назву вікна та іконку
		frame.setTitle("iFierce Traffic Simulator");
		frame.setIconImage(toolkit.getImage("res/icons/program_icon_32.png"));
	}
	
	/**
	 * Метод центрує позицію вхідного об'єкту.
	 * @param window Об'єкт типу {@link Window}.
	 */
	private void setPositionToCenter(Window window) {
		// Отримуємо розмір дисплею користувача
		Toolkit toolkit = Toolkit.getDefaultToolkit();
		Dimension dimension = toolkit.getScreenSize();		
		Double screenWidth = new Double(dimension.getWidth() / 2);
		Double screenHeight = new Double(dimension.getHeight() / 2);
		
		// Встановлюємо позицію вікна по центру
		int locationX = screenWidth.intValue() - (window.getWidth() / 2);
		int locationY = screenHeight.intValue() - (window.getHeight() / 2);
		window.setLocation(locationX, locationY);
	}
	
	/**
	 * Метод створює панель меню та здійснює налаштовування його основних компонентів.
	 */
	private void createMenuBar() {
		// Створюємо об'єкт панелі меню
		menuBar = new JMenuBar();
		
		// Створюємо меню <Файл>
		fileMenu = createFileMenu();
		
		// Створюємо меню <Додати>
		addMenu = createAddMenu();
		
		// Створюємо меню <Пуск>
		runMenu = createRunMenu();
		
		// Створюємо меню <Налаштування>
		settingsMenu = createSettingsMenu();
		
		// Створюємо меню <Допомога>
		helpMenu = createHelpMenu();
		
		// Додаємо створені меню до панелі
		menuBar.add(fileMenu);
		menuBar.add(addMenu);
		menuBar.add(runMenu);
		menuBar.add(settingsMenu);
		menuBar.add(helpMenu);
	}
	
	/**
	 * Метод створює та здійснює налаштовування меню <Файл>
	 * @return {@link JMenu} Об'єкт меню <Файл>
	 */
	private JMenu createFileMenu() {
		// Створюємо об'єкт меню <Файл>
		JMenu menu = new JMenu("Файл");
		
		// Створюємо пункти меню <Файл>
		JMenuItem newItem = new JMenuItem();
		newItem = new JMenuItem("Створити нову модель");
		newItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,
							   ActionEvent.CTRL_MASK));
		
		JMenuItem openItem = new JMenuItem();
		openItem = new JMenuItem("Відкрити...");
		openItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, 
								ActionEvent.CTRL_MASK));
		
		JMenuItem loadItem = new JMenuItem();
		loadItem = new JMenuItem("Завантажити модель з БД...");
		loadItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_B, 
								ActionEvent.CTRL_MASK));
		
		JMenuItem saveToFileItem = new JMenuItem();
		saveToFileItem = new JMenuItem("Зберегти як файл моделі");
		saveToFileItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, 
									  ActionEvent.CTRL_MASK));
		
		JMenuItem saveToDBItem = new JMenuItem();
		saveToDBItem = new JMenuItem("Зберегти модель до БД");
		saveToDBItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D,
									ActionEvent.CTRL_MASK));
		
		JMenuItem exitItem = new JMenuItem();
		exitItem = new JMenuItem("Вихід");
		exitItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X,
								ActionEvent.ALT_MASK));
		
		// Додаємо пункти в меню <Файл>
		menu.add(newItem);
		menu.add(openItem);
		menu.add(loadItem);
		menu.add(saveToFileItem);
		menu.add(saveToDBItem);
		menu.add(exitItem);
		
		return menu;
	}
	
	/**
	 * Метод створює та здійснює налаштовування меню <Додати>
	 * @return {@link JMenu} Об'єкт меню <Додати>
	 */
	private JMenu createAddMenu() {
		// Створюємо об'єкт меню <Додати>
		JMenu menu = new JMenu("Додати");
		
		// Створюємо пункти меню <Додати>
		JMenuItem addIntersectionItem = new JMenuItem();
 		addIntersectionItem = new JMenuItem("Перехрестя");
 		addIntersectionItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, 
 										ActionEvent.SHIFT_MASK));
 		
 		JMenuItem addSectionItem = new JMenuItem();
 		addSectionItem = new JMenuItem("Перегон");
 		addSectionItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, 
									  ActionEvent.SHIFT_MASK));
		
 		JMenuItem addTrafficLightItem = new JMenuItem();
		addTrafficLightItem = new JMenuItem("Світлофор");
		addTrafficLightItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T,
										ActionEvent.SHIFT_MASK));
 		
		// Додаємо пункти в меню <Додати>
		menu.add(addIntersectionItem);
		menu.add(addSectionItem);
		menu.add(addTrafficLightItem);
		
		return menu;
	}
	
	/**
	 * Метод створює та здійснює налаштовування меню <Пуск>
	 * @return {@link JMenu} Об'єкт меню <Пуск>
	 */
	private JMenu createRunMenu() {
		// Створюємо об'єкт меню <Пуск>
		JMenu menu = new JMenu("Пуск");
		
		// Створюємо пункти меню <Пуск>
		JMenuItem checkModelParamItem = new JMenuItem();
		checkModelParamItem = new JMenuItem("Перевірка параметрів моделі");
		checkModelParamItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C,
											ActionEvent.ALT_MASK));
		
		JMenuItem analysisItem = new JMenuItem();
  		analysisItem = new JMenuItem("Аналіз");
  		analysisItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, ActionEvent.ALT_MASK));
		
  		JMenuItem optimizationItem = new JMenuItem();
  		optimizationItem = new JMenuItem("Оптимізація");
  		optimizationItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,
  										ActionEvent.ALT_MASK));
  		
  		JMenuItem simStartStopItem = new JMenuItem();
		simStartStopItem = new JMenuItem("Розпочати / Закінчити моделювання");
		simStartStopItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, 
												ActionEvent.ALT_MASK));
  		
		// Додаємо пункти в меню <Пуск>
		menu.add(checkModelParamItem);
		menu.add(analysisItem);
		menu.add(optimizationItem);
		menu.add(simStartStopItem);
		
		return menu;
	}
	
	/**
	 * Метод створює меню <Налаштування>
	 * @return {@link JMenu} Об'єкт меню <Налаштування>
	 */
	private JMenu createSettingsMenu() {
		// Створюємо об'єкт меню <Налаштування>
		JMenu menu = new JMenu("Налаштування");
		
		// Створюємо пункти меню <Налаштування>
		JMenuItem modelSettingsItem = new JMenuItem();
  		modelSettingsItem = new JMenuItem("Параметри моделі");
  		
  		JMenuItem programPreferencesItem = new JMenuItem();
  		programPreferencesItem = new JMenuItem("Програмні налаштування");
		
		// Додаємо пункти в меню <Налаштування>
  		menu.add(modelSettingsItem);
  		menu.add(programPreferencesItem);
  		
  		return menu;
	}
	
	/**
	 * Метод створює та здійснює налаштовування меню <Допомога>
	 * @return {@link JMenu} Об'єкт меню <Допомога>
	 */
	private JMenu createHelpMenu() {
		// Створюємо об'єкт меню <Допомога>
		JMenu menu = new JMenu("Допомога");
		
		// Створюємо пункти меню <Допомога>
		JMenuItem helpContentsItem = new JMenuItem();
  		helpContentsItem = new JMenuItem("Інструкція користувача");
		
  		JMenuItem aboutItem = new JMenuItem();
  		aboutItem = new JMenuItem("Про iFierce Traffic Simulator");
  		
		// Додаємо пункти в меню <Допомога>
  		menu.add(helpContentsItem);
  		menu.add(aboutItem);
  		
  		return menu;
	}
	
	private void createToolBar() {
		// Створюємо об'єкт панелі інструментів
		toolBarPanel = new ToolBarPanel();
		
		// Встановлюємо диспетчер компонування та границі панелі інструментів
		toolBarPanel.setLayout(new BoxLayout(toolBarPanel, BoxLayout.X_AXIS));
		toolBarPanel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, 
				new Color(170, 176, 191)));
		
		// Створюємо кнопки, які міститиме панель інструментів
		ToolBarButton newButton = new ToolBarButton(new ImageIcon("res/icons/new.png"));
		newButton.setToolTipText("Створити нову модель перехрестя / вулиці");
		
		ToolBarButton openButton = new ToolBarButton(new ImageIcon("res/icons/open.png"));
		openButton.setToolTipText("Відкрити раніше збережену модель");
		
		ToolBarButton saveAsFileButton = new ToolBarButton(new ImageIcon("res/icons/save.png"));
		saveAsFileButton.setToolTipText("Зберегти модель до файлу");
		
		ToolBarButton saveToDBButton = new ToolBarButton(new ImageIcon("res/icons/saveToDB.png"));
		saveToDBButton.setToolTipText("Зберегти модель до БД");
		
		ToolBarButton intersectionButton = new ToolBarButton(
				new ImageIcon("res/icons/crossroad.png"));
		intersectionButton.setToolTipText("Додати перехрестя");
		
		ToolBarButton sectionButton = new ToolBarButton(
				new ImageIcon("res/icons/section.png"));
		sectionButton.setToolTipText("Додати квартал");
		
		// Створюємо розділювачі груп кнопок
		JLabel endFileLabel = new JLabel("|");
		endFileLabel.setForeground(new Color(170, 176, 191));
		endFileLabel.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 18));
		
		// Додаємо усі елементи до панелі інструментів
		toolBarPanel.add(newButton);
	}
}
